/*
PearReview - The peer review assistant.
Copyright (C) 2009  Dimitrij Pankratz, Anton Musichin
http://www.pearreview.com, info@pearreview.com

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

package com.pearreview.ui;

import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.Serializable;

import javax.swing.JComboBox;
import javax.swing.Timer;

public class FadingManager implements Serializable {
	private static final long serialVersionUID = -3713857850122543841L;

	private static FadingManager instance;
	public static final Color FADING_COLOR = new Color(234, 252, 191);
	public static final int ANIMATION_DURATION = 500;
	
	private FadingManager() {
		
	}
	
	public static FadingManager getInstance() {
		if(instance == null)
			instance = new FadingManager();
		return instance;
	}
	
	public void registerComponent(Component comp) {
		if(comp instanceof JComboBox) {
			registerComponent((JComboBox) comp);
		} else {
			comp.addFocusListener(new FadingListener(comp));
		}
	}
	
	public void registerComponent(JComboBox comp) {
		comp.addFocusListener(new FadingListener(comp));
		comp.getEditor().getEditorComponent().addFocusListener(
				new FadingListener(comp));
	}
	
	private class FadingListener implements ActionListener, FocusListener, 
			Serializable {
		private static final long serialVersionUID = 7379593924113900049L;
		private Component comp;
		private Timer timer;
		private long animStartTime;
		private Color currentColor;
		private Color startColor;
		public FadingListener(Component comp) {
			this.comp = comp;
			startColor = comp.getBackground();
			timer = new Timer(30, this);
		}

		@Override
		public void actionPerformed(ActionEvent ae) {
			// calculate elapsed fraction of animation
			long currentTime = System.nanoTime() / 1000000;
			long totalTime = currentTime - animStartTime;
			if (totalTime > ANIMATION_DURATION) {
				//animStartTime = currentTime;
				timer.stop();
			}
			float fraction = (float)totalTime / ANIMATION_DURATION;
			fraction = Math.min(1.0f, fraction);
			// interpolate between start and end colors with current fraction
			int red = (int)(fraction * FADING_COLOR.getRed() + 
					(1 - fraction) * startColor.getRed());
			int green = (int)(fraction * FADING_COLOR.getGreen() + 
					(1 - fraction) * startColor.getGreen());
			int blue = (int)(fraction * FADING_COLOR.getBlue() + 
					(1 - fraction) * startColor.getBlue());
			
			//check if red, green and blue are in allowed range (0 - 255)
			//to avoid not pretty exceptions :(
			if (red > 255) {red = 255;}
			if (green > 255) {green = 255;}
			if (blue > 255) {blue = 255;}
			
			if (red < 0) {red = 0;}
			if (green < 0) {green = 0;}
			if (blue < 0) {blue = 0;}
			
			// set the new color
			currentColor = new Color(red, green, blue);
			comp.setBackground(currentColor);

			// force a repaint to display the component with its new color
			comp.repaint();
		}

		@Override
		public void focusGained(FocusEvent e) {
			timer.setInitialDelay(10);
			animStartTime = 10 + System.nanoTime() / 1000000;
			timer.start();
		}

		@Override
		public void focusLost(FocusEvent e) {
			timer.stop();
			comp.setBackground(startColor);
			comp.repaint();
		}
	}
}
